home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
crossedit
/
Cnv
/
CnvPath.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
13KB
|
479 lines
/*
* CnvPath - file selector
* Copyright (C) 1993 Petri Heinila
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Author can be connected by email from hevi@lut.fi
*/
#include <Cnv.h>
#include <debug.h>
#include <assert.h>
/**********************************************************************
* declarations
**********************************************************************/
static void CnvPathListInit(CnvPath p);
static void CnvPathListGet(CnvPath p,String path);
static void CnvPathEnter(CnvPath self);
static Boolean hasActions = False;
static CnvPath tmpCnvPath = NULL;
/**********************************************************************
* actions
**********************************************************************/
static void CnvPathReturn(Widget w,XEvent *e,String *argv, Cardinal *argc);
static XtActionsRec actions[] = {
{"CnvPathReturn", CnvPathReturn} /* when user accept */
};
static void CnvPathReturn(Widget w,XEvent *e,String *argv, Cardinal *argc)
{
CnvPath self = (CnvPath)tmpCnvPath;
assert(self);
CnvPathEnter(self);
}
/**********************************************************************
* widgets
**********************************************************************/
static void CnvPathCancelCb(Widget w,XtPointer client,XtPointer call)
{
CnvPath p = (CnvPath)client;
p->hold = CnvPathCancel;
}
static void CnvPathEnterCb(Widget w,XtPointer client,XtPointer call)
{
CnvPath self = (CnvPath)client;
CnvPathEnter(self);
}
static void CnvPathSelectFileCb(Widget w,XtPointer client,XtPointer call)
{
CnvPath p = (CnvPath)client;
XawListReturnStruct *ret = (XawListReturnStruct*)call;
XtVaSetValues(p->text,
XtNstring,ret->string,
NULL);
}
static void CnvPathSelectDirCb(Widget w,XtPointer client,XtPointer call)
{
CnvPath p = (CnvPath)client;
XawListReturnStruct *ret = (XawListReturnStruct*)call;
char path[PATH_MAX+1];
if(strcmp(ret->string,"..") == 0) {
char *str;
pathcpy(path,p->current);
str = path + strlen(path);
while(*str != '/' && str > path) str--;
*str = 0;
} else if(strcmp(ret->string,".") == 0) {
sprintf(path,"%s",p->current);
} else {
sprintf(path,"%s/%s",p->current,ret->string);
}
p->hold = CnvPathHold;
CnvPathListGet(p,path);
}
/**********************************************************************
* Layout
**********************************************************************/
static void Layout(CnvPath self,String name)
{
Widget cont,cancel,fileView,dirView,ok;
self->shell = XtVaCreatePopupShell
(name,transientShellWidgetClass,cnv->shell,NULL);
cont = XtVaCreateManagedWidget
("cont",formWidgetClass,self->shell,
NULL);
self->cwd = XtVaCreateManagedWidget
("cwd",labelWidgetClass,cont,
/*
XtNfromHoriz,NULL,
XtNfromVert,NULL,
*/
NULL);
self->text = XtVaCreateManagedWidget
("text",asciiTextWidgetClass,cont,
XtNtype,XawAsciiString,
XtNeditType,XawtextEdit,
XtNfromHoriz,self->cwd,
XtNfromVert,NULL,
XtNaccelerators,XtParseAcceleratorTable
("#override <Key>Return: CnvPathReturn() \n"),
XtNtranslations,XtParseTranslationTable
("#override <Key>Tab: CnvNop()\n"
"<Key>Return: CnvPathReturn() \n"),
NULL);
fileView = XtVaCreateManagedWidget
("fileView",viewportWidgetClass,cont,
XtNfromHoriz,NULL,
XtNfromVert,self->cwd,
NULL);
self->fileList = XtVaCreateManagedWidget
("fileList",listWidgetClass,fileView,
XtNtranslations,XtParseTranslationTable
("#override <Btn1Up>(2): Set() Notify() CnvPathReturn()\n"
"<Btn1Down>: Set() Notify() \n"),
NULL);
XtAddCallback(self->fileList,XtNcallback,CnvPathSelectFileCb,
(XtPointer)self);
dirView = XtVaCreateManagedWidget
("dirView",viewportWidgetClass,cont,
XtNfromHoriz,fileView,
XtNfromVert,self->cwd,
NULL);
self->dirList = XtVaCreateManagedWidget
("dirList",listWidgetClass,dirView,
NULL);
XtAddCallback(self->dirList,XtNcallback,CnvPathSelectDirCb,(XtPointer)self);
ok = XtVaCreateManagedWidget
("ok",commandWidgetClass,cont,
XtNfromHoriz,NULL,
XtNfromVert,fileView,
NULL);
XtAddCallback(ok,XtNcallback,CnvPathEnterCb,(XtPointer)self);
cancel = XtVaCreateManagedWidget
("cancel",commandWidgetClass,cont,
XtNfromHoriz,ok,
XtNfromVert,fileView,
NULL);
XtAddCallback(cancel,XtNcallback,CnvPathCancelCb,(XtPointer)self);
XtInstallAllAccelerators(cont,cont);
}
/**********************************************************************
*
**********************************************************************/
/*
* function: select a filepath
*/
static void CnvPathEnter(CnvPath self)
{
String str;
self->hold = CnvPathOk;
XtVaGetValues(self->text,
XtNstring,&str,
NULL);
namecpy(self->filename,str);
}
/*
* implicit: App app
*/
static void CnvPathListInit(CnvPath p)
{
int i;
for(i=0; i < EntryMax; i++) {
/* debug1("i:%i\n",i); */
p->fileTable[i] = NULL;
}
for(i=0; i < EntryMax; i++) {
/* debug1("i2:%i\n",i); */
p->dirTable[i] = NULL;
}
p->fileNro = 0;
p->dirNro = 0;
*(p->filename) = 0;
}
/*
* compare funtion for sorting in CnvPathListGet()
*/
static int StrCmp (const void **s1, const void **s2)
{
return strcmp (*s1, *s2);
}
/*
* read files and directories from given absolute dir
* update them into Path structure. directoty is a crossfire
* part of file name ie. LibDir/MapDir<dirname>, althought
* it is absolute name in it part, ie it have to begin with '/'.
*/
static void CnvPathListGet(CnvPath self,String directory)
{
DIR *dir;
#ifdef NeXT
struct direct *dirent;
#else
struct dirent *dirent;
#endif
struct stat statbuf;
Cardinal i,fileOld,dirOld;
char path[PATH_MAX+1],full[PATH_MAX+1];
/*** form full dir name ***/
sprintf(full,"%s%s",self->root,directory);
debug1("CnvPathListGet(), rescan %s\n",full);
/*** open it ***/
if(CnvPathNoAccess(self->shell, full)) return;
if((dir = opendir(full)) == NULL) CnvDie(self->shell,full);
XtVaSetValues(self->cwd,
XtNlabel,directory,
NULL);
pathcpy(self->current,directory);
/*** read dir & files ***/
fileOld = self->fileNro;
dirOld = self->dirNro;
self->fileNro = 0;
self->dirNro = 0;
while((dirent = readdir(dir)) != NULL) {
sprintf(path,"%s/%s",full,dirent->d_name);
if (stat ((char *) path, &statbuf) == -1) {
perror (path);
continue;
}
if(S_ISDIR(statbuf.st_mode)) {
if(self->dirNro >= EntryMax) continue;
XtFree(self->dirTable[self->dirNro]);
self->dirTable[self->dirNro] = XtNewString(dirent->d_name);
self->dirNro++;
} else {
if(self->fileNro >= EntryMax) continue;
XtFree(self->fileTable[self->fileNro]);
self->fileTable[self->fileNro] = XtNewString(dirent->d_name);
self->fileNro++;
}
}
closedir(dir);
/*** free strings ***/
for(i = self->fileNro; i < fileOld; i++) {
XtFree(self->fileTable[i]);
self->fileTable[i] = NULL;
}
for(i = self->dirNro; i < dirOld; i++) {
XtFree(self->dirTable[i]);
self->dirTable[i] = NULL;
}
/*** sort tables ***/
qsort(self->fileTable,self->fileNro,sizeof(String),(int (*)())StrCmp);
qsort(self->dirTable,self->dirNro,sizeof(String),(int (*)())StrCmp);
/*** update ***/
XawListChange(self->fileList,self->fileTable,self->fileNro,0,True);
XawListChange(self->dirList,self->dirTable,self->dirNro,0,True);
}
/**********************************************************************
* public
**********************************************************************/
/*
* create new instance of file-selector, no show
* dir is crossfire path eg "/"
* name: name of this module
* root: all
* dir : starting directory
*/
CnvPath CnvPathCreate(String name,String root,String dir)
{
CnvPath self;
debug3("CnvPathCreate() %s %s %s\n",name,root,dir);
self = (CnvPath) XtMalloc (sizeof (struct CnvPath));
memset(self,0,sizeof(struct CnvPath));
pathcpy(self->root,root);
/*** initialize translations if not done ***/
if(hasActions == False) {
XtAppAddActions(XtWidgetToApplicationContext(cnv->shell),
actions,
XtNumber(actions));
hasActions = True;
}
Layout(self,name);
CnvPathListInit(self);
CnvCenterWidget(self->shell);
CnvPathListGet(self,dir);
return self;
}
/*
* remove instance of file-selector
*/
void CnvPathDestroy(CnvPath self)
{
int i;
debug("CnvPathDestroy()\n");
for(i=0;i<self->dirNro;i++) XtFree(self->dirTable[i]);
for(i=0;i<self->fileNro;i++) XtFree(self->fileTable[i]);
XtDestroyWidget(self->shell);
}
/*
* member: select a filepath
* return: PathResponce & results are in Path-structure
*/
CnvPathResponce CnvPathSelect(CnvPath self)
{
if(tmpCnvPath) {
CnvNotify("File Selector already in use",
"Continue",NULL);
return CnvPathCancel;
}
XtVaSetValues(self->text,
XtNstring,self->filename,
NULL);
/*** round ***/
tmpCnvPath = self;
self->hold = CnvPathHold;
XtPopup(self->shell,XtGrabExclusive);
while(self->hold == CnvPathHold) {
XtAppProcessEvent(XtWidgetToApplicationContext(self->shell),XtIMXEvent);
}
XtPopdown(self->shell);
tmpCnvPath = NULL;
return self->hold;
}
/*
* member: select a filepath
* return: PathResponce & results are in Path-structure
*/
CnvPathResponce CnvPathSelectAbs(CnvPath self,String path)
{
if(tmpCnvPath) {
CnvNotify("File Selector already in use",
"Continue",NULL);
return CnvPathCancel;
}
XtVaSetValues(self->text,
XtNstring,self->filename,
NULL);
/*** round ***/
tmpCnvPath = self;
self->hold = CnvPathHold;
XtPopup(self->shell,XtGrabExclusive);
while(self->hold == CnvPathHold) {
XtAppProcessEvent(XtWidgetToApplicationContext(self->shell),XtIMXEvent);
}
XtPopdown(self->shell);
tmpCnvPath = NULL;
sprintf(path,"%s%s/%s",self->root,self->current,self->filename);
return self->hold;
}
/**********************************************************************
* utility
**********************************************************************/
/*
* - path is full absolute name
* - return true if NO access
*/
Boolean CnvPathNoAccess(Widget w, String path)
{
char buf[BUFSIZ];
if (access (path, R_OK | X_OK) == -1) {
switch (errno) {
case EACCES:
sprintf (buf, "Permission denied for %s", path);
CnvNotify (buf,Continue,NULL);
break;
case ENOENT:
sprintf (buf, "%s does not exist", path);
CnvNotify (buf,Continue,NULL);
break;
case EIO:
sprintf (buf, "IO error in accessing %s", path);
CnvNotify (buf,Continue,NULL);
break;
case ENAMETOOLONG:
case ENOTDIR:
sprintf (buf, "Error in pathname for %s", path);
CnvNotify (buf,Continue);
break;
default:
sprintf (buf, "Error accessing to %s", path);
CnvNotify (buf,Continue,NULL);
break;
}
return True;
} else {
return False;
}
}
/*
* - path is full absolute name
* - return true if NO access
*/
Boolean CnvPathNoWrite(Widget w, String path)
{
char buf[BUFSIZ];
if (access (path, R_OK | W_OK) == -1) {
switch (errno) {
case EACCES:
sprintf (buf, "Permission denied for %s", path);
CnvNotify (buf,Continue,NULL);
break;
case ENOENT:
sprintf (buf, "%s does noit exist", path);
CnvNotify (buf,Continue,NULL);
break;
case EIO:
sprintf (buf, "IO error in accessing %s", path);
CnvNotify (buf,Continue,NULL);
break;
case ENAMETOOLONG:
case ENOTDIR:
sprintf (buf, "Error in pathname for %s", path);
CnvNotify (buf,Continue);
break;
default:
sprintf (buf, "Error accessing to %s", path);
CnvNotify (buf,Continue,NULL);
break;
}
return True;
} else {
return False;
}
}
/*** end of CnvPath.c ***/